package cn.zx.rmq.producer;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.common.RemotingHelper;

import java.io.UnsupportedEncodingException;

/**
 * @Package: cn.zx.rmq.producer
 * @ClassName: TransactionProducer
 * @Author: Think
 * @CreateTime: 2021/6/28 16:12
 * @Description: 分布式事务-两阶段提交-解决本地事务和发送消息之间原子操作的问题
 */
@Slf4j
public class TransactionProducer {

    public static void main(String[] args) throws MQClientException, UnsupportedEncodingException {
        TransactionMQProducer producer = new TransactionMQProducer("TransactionProducer-Group");
        producer.setNamesrvAddr("localhost:9876");

        TransactionListener transactionListener = new TransactionListener() {
            // 自己触发，本地事务开始处理
            @Override
            public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
                log.info("开始提交事务{}", msg.getTags());
                if (StringUtils.equals("about-transaction2", msg.getTags())) {
                    // 只有明确commit的消息才会被消费者消费
                    return LocalTransactionState.COMMIT_MESSAGE;
                } else if (StringUtils.equals("about-transaction4", msg.getTags())) {
                    // rollback的消息不会被mq发送给消费者
                    return LocalTransactionState.ROLLBACK_MESSAGE;
                }
                // unknow的消息等一会MQ会来回查
                return LocalTransactionState.UNKNOW;
            }

            // 供MQ调用，事务消息回查
            @Override
            public LocalTransactionState checkLocalTransaction(MessageExt msg) {
                log.info("当前MQ回查消息的TAG为：{}", msg.getTags());
                return LocalTransactionState.COMMIT_MESSAGE;
            }
        };

        producer.setTransactionListener(transactionListener);
        producer.start();

        for (int i = 0; i < 5; i++) {
            Message msg = new Message("KYC", "about-transaction" + i, ("客户拥有金额为：" + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
            SendResult sendResult = producer.sendMessageInTransaction(msg, null);
            log.info("发送返回信息为：{}", sendResult);
        }

        // 生产者停止后，MQ将不能回查消息
        //producer.shutdown();
        log.info("所有消息发送完毕！");
    }

}
